package com.yxh.www.author.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yxh.www.author.domain.SmUser;
import com.yxh.www.author.dto.SmResourceTree;
import com.yxh.www.author.dto.SmUserToken;
import com.yxh.www.author.mapper.SmResourceMapper;
import com.yxh.www.author.mapper.SmUserMapper;
import com.yxh.www.author.service.SmUserService;
import com.yxh.www.common.constant.Constant;
import com.yxh.www.common.result.Result;
import com.yxh.www.common.result.ResultBuilder;
import com.yxh.www.common.result.ResultEnum;
import com.yxh.www.common.util.JwtTokenUtil;
import com.yxh.www.common.util.MapBeanUtil;
import com.yxh.www.common.util.PBKDF2Util;
import com.yxh.www.common.util.TreeTableUtil;
import com.yxh.www.mysql.base.BaseServiceImpl;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 系统用户表 服务实现类
 * </p>
 *
 * @author Yangxiaohui
 * @since 2020-05-08
 */
@Service
public class SmUserServiceImpl extends BaseServiceImpl<SmUserMapper, SmUser> implements SmUserService {
    private final RedisTemplate<String, Object> redisTemplate;
    private final SmResourceMapper smResourceMapper;

    public SmUserServiceImpl(RedisTemplate<String, Object> redisTemplate, SmResourceMapper smResourceMapper) {
        this.redisTemplate = redisTemplate;
        this.smResourceMapper = smResourceMapper;
    }

    @Override
    public Result<Object> addSmUser(String userName, String userPhone, String loginPass, String userPhoto, String userMail) {
        // 判断该用户信息是否重复
        int countUserByPhoneOrName = baseMapper.selectCount(new QueryWrapper<SmUser>()
                .eq("user_phone", userPhone)
                .or()
                .eq("user_name", userName)
        );
        if (countUserByPhoneOrName != 0) {
            return ResultBuilder.error(ResultEnum.USER_HANDEL_ERROR, "用户名或手机号已存在！");
        }
        // 初始化用户并持久化 密码MD5加密

        SmUser smUser = new SmUser(userName, userPhone, PBKDF2Util.buildEncryptedPassword(loginPass), userPhoto, userMail);
        smUser.setCreateTime(LocalDateTime.now());
        return smUser.insert() ? ResultBuilder.success() : ResultBuilder.error("用户新增失败！");
    }

    @Override
    public Result<Object> modifySmUser(String id, String userName, String userPhone, String loginPass, String userPhoto, String userMail) {
        // 如果密码不为空，加密密码
        if (StringUtils.isNotBlank(loginPass)) {
            loginPass = DigestUtils.md5Hex(loginPass);
        }
        // 持久化
        SmUser smUser = new SmUser(id, userName, userPhone, loginPass, userPhoto, userMail);
        return smUser.updateById() ? ResultBuilder.success() : ResultBuilder.error("用户修改失败！");
    }

    @Override
    public Result<Object> removeSmUser(String id) {
        SmUser smUser = new SmUser();
        return smUser.deleteById() ? ResultBuilder.success() : ResultBuilder.error("用户删除失败！");
    }

    @Override
    public Result<Object> removeSmUsers(String[] id) {
        baseMapper.deleteBatchIds(Arrays.asList(id));
        return ResultBuilder.success();
    }

    @Override
    public Result<Object> listSmUser(String userName, String userPhone, String userMail) {
        return ResultBuilder.success(baseMapper.selectList(this.builderQueryListWrapper(userName, userPhone, userMail)));
    }

    @Override
    public Result<Object> pageSmUser(String userName, String userPhone, String userMail, Long pageNum, Long pageSize) {
        return ResultBuilder.success(baseMapper.selectPage(new Page<>(pageNum, pageSize), this.builderQueryListWrapper(userName, userPhone, userMail)));
    }

    @Override
    public Result<Object> authorSmUser(String userName, String userPhone, String loginPass) {
        // 如果用户名和手机号都没输入
        if (StringUtils.isBlank(userName) && StringUtils.isBlank(userPhone)) {
            return ResultBuilder.error(ResultEnum.USER_HANDEL_ERROR, "无效的用户民或手机号码！");
        }
        // 加密密码
        loginPass = PBKDF2Util.buildEncryptedPassword(loginPass);
        // 构建查询条件
        QueryWrapper<SmUser> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(userName)) {
            queryWrapper.eq("user_name", userName);
        } else {
            queryWrapper.eq("user_phone", userPhone);
        }
        queryWrapper.eq("login_pass", loginPass);
        // 验证登录信息
        if (baseMapper.selectCount(queryWrapper) == 0) {
            return ResultBuilder.error(ResultEnum.USER_HANDEL_ERROR, "账号或密码错误！");
        }
        // 获取用户
        SmUser smUser = baseMapper.selectOne(queryWrapper);
        // Token有效期
        long ttlMillis = 31557600000L;
        // 生成Token 有效期1天
        String token = JwtTokenUtil.buildToken(smUser.getId(), JwtTokenUtil.TokenType.LOGIN_TOKEN, ttlMillis, MapBeanUtil.object2Map(smUser));
        // 获取用户权限标识列表
        Set<String> smUserPermissionKeys = smResourceMapper.listSmUserPermissionKeysBySmUserId(smUser.getId());
        // 获取用户权限资源列表
        List<SmResourceTree> resourceList = smResourceMapper.listSmResourceBySmUserId(smUser.getId());
        List<SmResourceTree> resourceTreeList = TreeTableUtil.listToTreeList(resourceList, "id", "parentId", "children");
        // 放入Redis
        SmUserToken smUserToken = new SmUserToken(token, smUserPermissionKeys, smUser, resourceTreeList);
        redisTemplate.opsForValue().set(Constant.REDIS_USER_TOKEN_KEY_PREFIX + token, smUserToken, ttlMillis, TimeUnit.MILLISECONDS);
        return ResultBuilder.success(smUserToken);
    }


    /**
     * 初始化列表查询条件
     *
     * @param userName  用户名称
     * @param userPhone 手机号码
     * @param userMail  用户邮箱
     * @return 查询条件 {@link QueryWrapper<SmUser>}
     */
    private QueryWrapper<SmUser> builderQueryListWrapper(String userName, String userPhone, String userMail) {
        QueryWrapper<SmUser> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(userName)) {
            queryWrapper.like("user_name", userName);
        }
        if (StringUtils.isNotBlank(userPhone)) {
            queryWrapper.like("user_phone", userPhone);
        }
        if (StringUtils.isNotBlank(userMail)) {
            queryWrapper.like("user_mail", userMail);
        }
        return queryWrapper;
    }
}
